package com.tsd.jxc.sale.service.impl;

import com.tsd.common.vo.BatchDeleteLogicVo;
import com.tsd.core.constants.Constants;
import com.tsd.core.datasource.DataSourceContextHolder;
import com.tsd.core.thread.ThreadPoolTaskUtil;
import com.tsd.core.utils.DoubleUtil;
import com.tsd.core.utils.HlpUtils;
import com.tsd.core.utils.ListUtil;
import com.tsd.core.vo.HlpException;
import com.tsd.core.vo.PageBean;
import com.tsd.jxc.buy.entity.JxcBuyOrderDetailExt;
import com.tsd.jxc.goods.entity.JxcGoodsPriceExt;
import com.tsd.jxc.goods.service.JxcGoodsPriceService;
import com.tsd.jxc.sale.dao.JxcSaleOrderDetailMapper;
import com.tsd.jxc.sale.dao.JxcSaleOrderMapper;
import com.tsd.jxc.sale.entity.JxcSaleOrderDetail;
import com.tsd.jxc.sale.entity.JxcSaleOrderDetailExt;
import com.tsd.jxc.sale.entity.JxcSaleOrderExt;
import com.tsd.jxc.sale.entity.JxcSaleQuotationDetailExt;
import com.tsd.jxc.sale.service.JxcSaleOrderDetailService;
import com.tsd.jxc.setting.service.JxcSettingService;
import com.tsd.jxc.stock.StockConstants;
import com.tsd.jxc.utils.JxcUtils;
import com.tsd.jxc.vo.JxcSettingVo;
import com.tsd.service.BaseServiceImpl;
import com.tsd.system.entity.SysUser;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * 描述：JxcSaleOrderDetail 服务实现层
 *
 * @author Hillpool
 * @date 2022/07/29 15:04:27
 */
@Service
public class JxcSaleOrderDetailServiceImpl extends BaseServiceImpl implements JxcSaleOrderDetailService {

    @Resource
    private JxcSaleOrderDetailMapper jxcSaleOrderDetailMapper;
    @Resource
    private JxcSaleOrderMapper jxcSaleOrderMapper;
    @Resource
    private JxcSettingService jxcSettingService;
    @Resource
    private JxcGoodsPriceService jxcGoodsPriceService;

    @Override
    public JxcSaleOrderDetail getJxcSaleOrderDetailById(Long id) throws Exception {
        return jxcSaleOrderDetailMapper.selectByPrimaryKey(id);
    }

    @Override
    public JxcSaleOrderDetailExt queryBySid(String sid) throws Exception {
        return jxcSaleOrderDetailMapper.selectBySid(sid);
    }

    @Override
    public List<JxcSaleOrderDetailExt> queryValidByOrderList(List<String> order_list) {
        List<JxcSaleOrderDetailExt> detailExtList = ThreadPoolTaskUtil.queryInList4Split(order_list, list -> {
            JxcSaleOrderDetailExt params = new JxcSaleOrderDetailExt();
            params.setDr(0);
            params.setOrder_list(list);
            return jxcSaleOrderDetailMapper.selectByEntity(params);
        });
        if (!HlpUtils.isEmptyList(detailExtList)) {
            List<String> goodsList = ListUtil.map(detailExtList, JxcSaleOrderDetailExt::getGoods_sid);
            List<JxcGoodsPriceExt> priceExtList = jxcGoodsPriceService.queryByGoodsList(goodsList);
            for (JxcSaleOrderDetailExt detailExt : detailExtList) {
                List<JxcGoodsPriceExt> filters = ListUtil.filter(priceExtList, t -> t.getGoods_sid().equals(detailExt.getGoods_sid()));
                detailExt.setPrice_list(filters);
                detailExt.calcGoodsPrice();
            }
        }
        return detailExtList;
    }

    @Override
    public void deleteJxcSaleOrderDetails(List<String> list, SysUser opUser) throws Exception {
        for (String sid : list) {
            JxcSaleOrderDetail old = jxcSaleOrderDetailMapper.selectBySid(sid);
            super.checkEmpty(old, "该记录不存在");
            super.autoInjectBaseData(old, opUser, TYPE_DELETE);
            jxcSaleOrderDetailMapper.updateByPrimaryKeySelective(old);
        }
    }

    @Override
    public void saveJxcSaleOrderDetail(JxcSaleOrderDetail record, SysUser opUser) throws Exception {
        if (HlpUtils.isEmpty(record.getId())) {
            super.autoInjectBaseData(record, opUser, this.TYPE_CREATE);
            jxcSaleOrderDetailMapper.insertSelective(record);
        } else {
            super.autoInjectBaseData(record, opUser, this.TYPE_UPDATE);
            jxcSaleOrderDetailMapper.updateByPrimaryKeySelective(record);
        }
    }

    @Override
    public void saveJxcSaleOrderDetail(JxcSaleOrderExt record, SysUser opUser) throws Exception {
        List<JxcSaleOrderDetailExt> detailExtList = record.getDetail_list();
        super.checkEmptyList(detailExtList, "订单明细不能为空");

        List<Long> existIdList = ListUtil.filterMap(detailExtList, t -> !HlpUtils.isEmpty(t.getId()), JxcSaleOrderDetailExt::getId);

        JxcSaleOrderDetailExt params = new JxcSaleOrderDetailExt();
        params.setDr(0);
        params.setOrder_sid(record.getSid());
        List<JxcSaleOrderDetailExt> oldList = jxcSaleOrderDetailMapper.selectByEntity(params);

        //删除不存在订单明细
        List<Long> delIds = ListUtil.filterMap(oldList, t -> !existIdList.contains(t.getId()), JxcSaleOrderDetailExt::getId);
        if (!HlpUtils.isEmptyList(delIds)) {
            BatchDeleteLogicVo logicVo = new BatchDeleteLogicVo(opUser);
            logicVo.setIdList(delIds);
            jxcSaleOrderDetailMapper.deleteLogicByIdList(logicVo);
        }

        JxcSettingVo settingVo = JxcUtils.getJxcSettingVo();

        List<JxcSaleOrderDetailExt> insertList = new ArrayList<>();
        List<JxcSaleOrderDetailExt> updateList = new ArrayList<>();
        double totalQty = 0D, totalAmount = 0D, totalCost = 0D, totalTaxAmount = 0D;
        for (JxcSaleOrderDetailExt detailExt : detailExtList) {
            if (HlpUtils.isEmpty(detailExt.getPay_req_state())) {
                detailExt.setPay_req_state(Constants.VALUE_NO);
            }
            if (HlpUtils.isEmpty(detailExt.getOut_bill())) {
                detailExt.setOut_bill(StockConstants.DETAIL_IN_OUT_BILL_NONE);
            }
            super.checkEmpty(detailExt.getQty(), "第" + detailExt.getSn() + "项明细数量不能为空");
            super.checkEmpty(detailExt.getPrice(), "第" + detailExt.getSn() + "项明细销售价格不能为空");
            detailExt.setOrder_sid(record.getSid());
            detailExt.calc(record, settingVo);
            totalQty = DoubleUtil.add(totalQty, detailExt.getQty());
            totalAmount = DoubleUtil.add(totalAmount, detailExt.getAmount());
            double buyCost = DoubleUtil.mul(detailExt.getQty(), detailExt.getAvg_cost());
            totalCost = DoubleUtil.add(totalCost, buyCost);
            totalTaxAmount = DoubleUtil.add(totalTaxAmount, detailExt.getTax_amount());
            if (HlpUtils.isEmpty(detailExt.getId())) {
                super.autoInjectBaseData(detailExt, opUser, this.TYPE_CREATE);
                insertList.add(detailExt);
            } else {
                super.autoInjectBaseData(detailExt, opUser, this.TYPE_UPDATE);
                updateList.add(detailExt);
            }
        }
        if (!HlpUtils.isEmptyList(insertList)) {
            ThreadPoolTaskUtil.executeInList4Split(insertList, false, itemList -> jxcSaleOrderDetailMapper.insertList(itemList));
        }
        if (!HlpUtils.isEmptyList(updateList)) {
            ThreadPoolTaskUtil.executeInList4Split(updateList, false, itemList -> jxcSaleOrderDetailMapper.updateList(itemList));
        }

        record.setQty(BigDecimal.valueOf(totalQty));
        record.setAmount(BigDecimal.valueOf(totalAmount));
        record.setTotal_cost(BigDecimal.valueOf(totalCost));
        record.setTax_amount(BigDecimal.valueOf(totalTaxAmount));
        double grossProfit = DoubleUtil.sub(totalAmount, totalCost);
        record.setGross_profit(BigDecimal.valueOf(grossProfit));
        double profitRate = DoubleUtil.div(grossProfit, totalCost);
        record.setProfit_rate(BigDecimal.valueOf(profitRate));
        double grossProfitRate = DoubleUtil.div(grossProfit, totalAmount);
        record.setGross_profit_rate(BigDecimal.valueOf(grossProfitRate));
        double total = DoubleUtil.add(totalAmount, totalTaxAmount);
        if (!HlpUtils.isEmpty(record.getFree_shipping()) && record.getFree_shipping() == 1) {
            record.setTotal_amount(BigDecimal.valueOf(total));
        } else {
            double value = DoubleUtil.add(total, record.getReal_freight());
            record.setTotal_amount(BigDecimal.valueOf(value));
        }

        double shouldReceiveAmount = record.getTotal_amount().doubleValue();
        if (!HlpUtils.isEmpty(record.getIgnore_amount())) {
            shouldReceiveAmount = DoubleUtil.sub(shouldReceiveAmount, record.getIgnore_amount());
        }
        record.setShould_receive_amount(BigDecimal.valueOf(shouldReceiveAmount));

        double unReceiveAmount = record.getShould_receive_amount().doubleValue();
        if (!HlpUtils.isEmpty(record.getReceived_amount())) {
            unReceiveAmount = DoubleUtil.sub(unReceiveAmount, record.getReceived_amount());
        }
        if (unReceiveAmount < 0) {
            throw new HlpException("已收金额不能大于应收金额");
        }
        record.setUn_receive_amount(BigDecimal.valueOf(unReceiveAmount));
        jxcSaleOrderMapper.updateByPrimaryKeySelective(record);
    }

    @Override
    public List<JxcSaleOrderDetailExt> findJxcSaleOrderDetails(Map<String, Object> params, PageBean page) throws Exception {
        return jxcSaleOrderDetailMapper.selectByPage(params, page);
    }

    @Override
    public List<JxcSaleOrderDetailExt> findJxcSaleOrderDetails(Map<String, Object> params) throws Exception {
        return jxcSaleOrderDetailMapper.selectByParams(params);
    }

    @Override
    public List<JxcSaleOrderDetailExt> findJxcSaleOrderDetails4Sale2Buy(Map<String, Object> params, PageBean page) throws Exception {
        List<JxcSaleOrderDetailExt> list = jxcSaleOrderDetailMapper.selectByPage(params,page);
        if (!HlpUtils.isEmptyList(list)) {
            List<JxcSaleOrderDetailExt> buyList = jxcSaleOrderDetailMapper.selectBuyInfo(list);
            for (JxcSaleOrderDetailExt t:list){
                List<JxcSaleOrderDetailExt> filter = ListUtil.filter(buyList,item->t.getSid().equals(item.getSid()));
                if (filter.size()>0){
                    t.setGen_buy_qty4base(filter.get(0).getGen_buy_qty4base());
                    t.setGen_base_unit_name(filter.get(0).getGen_base_unit_name());
                }
            }
        }
        return list;
    }

    @Override
    public List<JxcSaleOrderDetailExt> queryJxcSaleOrderDetailList4Return(Map<String, Object> params, PageBean page) throws Exception {
        List<JxcSaleOrderDetailExt> detailExtList = jxcSaleOrderDetailMapper.selectValid4ReturnByPage(params, page);
        if (!HlpUtils.isEmptyList(detailExtList)) {
            List<String> goodsList = ListUtil.map(detailExtList, JxcSaleOrderDetailExt::getGoods_sid);
            List<JxcGoodsPriceExt> priceExtList = jxcGoodsPriceService.queryByGoodsList(goodsList);
            for (JxcSaleOrderDetailExt detailExt : detailExtList) {
                List<JxcGoodsPriceExt> filters = ListUtil.filterCopy(priceExtList, t -> t.getGoods_sid().equals(detailExt.getGoods_sid()), JxcGoodsPriceExt.class);
                if (!HlpUtils.isEmptyList(filters)) {
                    double qty = DoubleUtil.sub(detailExt.getQty4base(), detailExt.getReturn_qty4base());
                    double amount = DoubleUtil.sub(detailExt.getTotal_amount(), detailExt.getReturn_amount());
                    double baseUnitPrice = DoubleUtil.div(amount, qty, 4);
                    for (JxcGoodsPriceExt priceExt : filters) {
                        priceExt.setBuy_price(BigDecimal.valueOf(DoubleUtil.mul(baseUnitPrice, priceExt.getQty())));
                    }
                }
                detailExt.setPrice_list(filters);
            }
        }
        return detailExtList;
    }

}
